<!DOCTYPE html>
<html>

<head>
  <title>React组件化开发</title>
  <meta charset='utf-8'>
  <link href='https://cdn.maxiang.io/res-min/themes/marxico.css' rel='stylesheet'>
  <style>
    #preview-contents {
      margin-top: -20px;
    }
  </style>
</head>

<body>
  <div id='preview-contents' class='note-content'>
    <h3 id="react组件化开发">React组件化开发</h3>
    <blockquote>
      <p>组件化开发的优势</p>
      <ul>
        <li>
          <p>利于团队协作开发</p>
        </li>
        <li>
          <p>利于组件复用</p>
        </li>
        <li>
          <p>利于SPA单页面应用开发</p>
        </li>
        <li>
          <p>……</p>
        </li>
      </ul>
    </blockquote>

    <p><strong>Vue中的组件化开发：</strong> <br>
      <a href="http://fivedodo.com/upload/html/vuejs3/guide/migration/functional-components.html"
        target="_blank">http://fivedodo.com/upload/html/vuejs3/guide/migration/functional-components.html</a>
    </p>
    <ol>
      <li rel="1">
        <p>全局组件和局部组件</p>
      </li>
      <li rel="2">
        <p>函数组件（functional）和类组件「Vue3不具备functional函数组件」</p>
      </li>
    </ol>

    <p><strong>React中的组件化开发：</strong> <br>
      没有明确全局和局部的概念「可以理解为都是局部组件，不过可以把组件注册到React上，这样每个组件中只要导入React即可使用」</p>
    <ol>
      <li rel="1">
        <p>函数组件</p>
      </li>
      <li rel="2">
        <p>类组件</p>
      </li>
      <li rel="3">
        <p>Hooks组件：在函数组件中使用React Hooks函数</p>
      </li>
    </ol>

    <h4 id="函数组件">函数组件</h4>
    <p>创建一个函数返回jsx元素</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-comment">// views/FunctionComponent.jsx</span>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> FunctionComponent = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">FunctionComponent</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        我是函数组件</span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> FunctionComponent;
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-comment">// index.jsx</span>
</div><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> FunctionComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'@/views/FunctionComponent'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>));
</div><div class="hljs-line">root.render(
</div><div class="hljs-line">  <span class="xml"><span class="hljs-tag">&lt;&gt;</span></span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;<span class="hljs-name">FunctionComponent</span>/&gt;</span></span>
</div><div class="hljs-line"><span class="xml">  <span class="hljs-tag">&lt;/&gt;</span></span>
</div><div class="hljs-line"><span class="xml">);</span>
</div></code></pre>

    <p>在JSX元素渲染的时候，如果type是函数，则把函数执行！</p>
    <ul>
      <li>
        <p>会把解析出来的props「含children」，传递给函数</p>
        <ul>
          <li>
            <p>单闭合和双闭合调用的区别「插槽」</p>
          </li>
          <li>
            <p>React.Children</p>
          </li>
          <li>
            <p>props是只读的「被冻结」</p>
          </li>
        </ul>
      </li>
      <li>
        <p>props的规则设置</p>
        <ul>
          <li>
            <p>设置默认值</p>
          </li>
          <li>
            <p>设置属性规则「基于prop-types插件」</p>
          </li>
        </ul>
      </li>
      <li>
        <p>属性和插槽都可以让组件具备更强的复用性</p>
      </li>
    </ul>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-comment">// index.jsx</span>
</div><div class="hljs-line">root.render(
</div><div class="hljs-line">  <span class="xml"><span class="hljs-tag">&lt;&gt;</span></span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;<span class="hljs-name">FunctionComponent</span> <span class="hljs-attr">x</span>=<span class="hljs-string">{10}</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"你好世界"</span> <span class="hljs-attr">arr</span>=<span class="hljs-string">{[10,</span> <span class="hljs-attr">20</span>, <span class="hljs-attr">30</span>]}&gt;</span></span>
</div><div class="hljs-line"><span class="xml">      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'slot-box'</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        我是插槽信息</span>
</div><div class="hljs-line"><span class="xml">      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">FunctionComponent</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">  <span class="hljs-tag">&lt;/&gt;</span></span>
</div><div class="hljs-line"><span class="xml">);</span>
</div></code></pre>

    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-comment">// views/FunctionComponent.jsx</span>
</div><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> PropTypes <span class="hljs-keyword">from</span> <span class="hljs-string">'prop-types'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">const</span> FunctionComponent = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">FunctionComponent</span>(<span class="hljs-params">props</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-comment">/* 被冻结:不能修改/新增/删除/劫持...「可以赋值给其它状态再进行修改」 */</span>
</div><div class="hljs-line">    <span class="hljs-comment">// console.log(Object.isFrozen(props)); //-&gt;true</span>
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">/* 对props.children进行操作：count/forEach/map/toArray... */</span>
</div><div class="hljs-line">    <span class="hljs-comment">// console.log(React.Children);</span>
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        我是函数组件</span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-comment">// 赋值属性默认值</span>
</div><div class="hljs-line">FunctionComponent.defaultProps = {
</div><div class="hljs-line">    <span class="hljs-attr">x</span>: <span class="hljs-number">0</span>,
</div><div class="hljs-line">    <span class="hljs-attr">title</span>: <span class="hljs-string">''</span>,
</div><div class="hljs-line">    <span class="hljs-attr">arr</span>: [],
</div><div class="hljs-line">    <span class="hljs-attr">num</span>: <span class="hljs-number">0</span>
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-comment">// 设置属性规则</span>
</div><div class="hljs-line">FunctionComponent.propTypes = {
</div><div class="hljs-line">    <span class="hljs-attr">x</span>: PropTypes.number,
</div><div class="hljs-line">    <span class="hljs-attr">title</span>: PropTypes.string.isRequired,
</div><div class="hljs-line">    <span class="hljs-attr">arr</span>: PropTypes.array,
</div><div class="hljs-line">    <span class="hljs-attr">num</span>: PropTypes.any
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> FunctionComponent;
</div></code></pre>

    <p>实现具名插槽</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-comment">// index.jsx</span>
</div><div class="hljs-line">root.render(
</div><div class="hljs-line">  <span class="xml"><span class="hljs-tag">&lt;&gt;</span></span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;<span class="hljs-name">FunctionComponent</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'slot-box'</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"head"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        我是插槽信息1</span>
</div><div class="hljs-line"><span class="xml">      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'slot-box'</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"foot"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        我是插槽信息2</span>
</div><div class="hljs-line"><span class="xml">      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">FunctionComponent</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">  <span class="hljs-tag">&lt;/&gt;</span></span>
</div><div class="hljs-line"><span class="xml">);</span>
</div></code></pre>

    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-comment">// views/FunctionComponent.jsx</span>
</div><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">const</span> FunctionComponent = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">FunctionComponent</span>(<span class="hljs-params">props</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">let</span> children = React.Children.toArray(props.children),
</div><div class="hljs-line">        headSlots = children.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.props.slot === <span class="hljs-string">'head'</span>),
</div><div class="hljs-line">        footSlots = children.filter(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.props.slot === <span class="hljs-string">'foot'</span>);
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        {headSlots}</span>
</div><div class="hljs-line"><span class="xml">        我是组件内容</span>
</div><div class="hljs-line"><span class="xml">        {footSlots}</span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> FunctionComponent;
</div></code></pre>

    <p>函数组件是<code>静态组件</code></p>
    <ul>
      <li>
        <p>不具备状态、生命周期函数、ref等内容</p>
      </li>
      <li>
        <p>第一次渲染完毕，除非父组件控制其重新渲染，否则内容不会再更新</p>
      </li>
      <li>
        <p>优势：渲染速度快</p>
      </li>
      <li>
        <p>弊端：静态组件，无法实现组件动态更新</p>
      </li>
    </ul>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">const</span> FunctionComponent = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">FunctionComponent</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">let</span> num = <span class="hljs-number">0</span>;
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        {num}</span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> {</span>
</div><div class="hljs-line"><span class="xml">            num++;</span>
</div><div class="hljs-line"><span class="xml">            console.log(num); //变量值累加，但是组件不会重新渲染</span>
</div><div class="hljs-line"><span class="xml">        }}&gt;增加<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> FunctionComponent;
</div></code></pre>


    <h4 id="类组件">类组件</h4>
    <p>创建一个<code>类</code>，并继承<code>React.Component/PureComponent</code>，基于<code>render</code>返回JSX视图</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</div><div class="hljs-line"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ClassComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{
</div><div class="hljs-line">    render() {
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            我是类组件</span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
</div><div class="hljs-line">    }
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ClassComponent;
</div></code></pre>

    <p>类组件是<code>动态组件</code></p>
    <ul>
      <li>
        <p>具备属性及规则校验</p>
      </li>
      <li>
        <p>具备状态，修改状态可以控制视图更新</p>

        <ul>
          <li>
            <p>setState</p>
          </li>
          <li>
            <p>forceUpdate</p>
          </li>
        </ul>
      </li>
      <li>
        <p>具备周期函数</p>

        <ul>
          <li>
            <p>严格模式下，一些不安全的周期函数是禁止使用的</p>
          </li>
        </ul>
      </li>
    </ul>
    
    <p><img longdesc="./1657471498194.png" width="600" alt="Alt text" title="" type="image/png"
        src=""
        class=""></p>
    <h4 id="purecomponent-pjʊər">PureComponent /pjʊə(r)/</h4>
    <p>一个小测试：新状态值和原始状态值是相同的堆内存地址「数据发生改变」，我们可以试试继承React.Component和React.PureComponent的区别？</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Demo</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{
</div><div class="hljs-line">    state = {
</div><div class="hljs-line">        <span class="hljs-attr">arr</span>: [<span class="hljs-number">10</span>, <span class="hljs-number">20</span>, <span class="hljs-number">30</span>]
</div><div class="hljs-line">    };
</div><div class="hljs-line">    handler = <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
</div><div class="hljs-line">        <span class="hljs-keyword">this</span>.state.arr.push(<span class="hljs-number">40</span>);
</div><div class="hljs-line">        <span class="hljs-keyword">this</span>.setState({ <span class="hljs-attr">arr</span>: <span class="hljs-keyword">this</span>.state.arr });
</div><div class="hljs-line">    };
</div><div class="hljs-line">    render() {
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"demo"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            {this.state.arr.join('+')}</span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{this.handler}</span>&gt;</span>更改<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
</div><div class="hljs-line">    }
</div><div class="hljs-line">};
</div></code></pre>

    <p>自动增加shouldComponentUpdate周期函数，并对原始属性/状态和最新属性/状态进行<code>浅比较</code></p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">const</span> shallowEqual = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">shallowEqual</span>(<span class="hljs-params">objA, objB</span>)</span>{
</div><div class="hljs-line">  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Object</span>.is(objA, objB))  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
</div><div class="hljs-line">  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> objA !== <span class="hljs-string">'object'</span> || objA === <span class="hljs-literal">null</span> ||
</div><div class="hljs-line">      <span class="hljs-keyword">typeof</span> objB !== <span class="hljs-string">'object'</span> || objB === <span class="hljs-literal">null</span>) {
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
</div><div class="hljs-line">  }
</div><div class="hljs-line">  <span class="hljs-keyword">const</span> keysA = <span class="hljs-built_in">Reflect</span>.ownKeys(objA),
</div><div class="hljs-line">        keysB = <span class="hljs-built_in">Reflect</span>.ownKeys(objB);
</div><div class="hljs-line">  <span class="hljs-keyword">if</span> (keysA.length !== keysB.length) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
</div><div class="hljs-line">  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; keysA.length; i++) {
</div><div class="hljs-line">    <span class="hljs-keyword">let</span> key = keysA[i];
</div><div class="hljs-line">    <span class="hljs-keyword">if</span> (
</div><div class="hljs-line">      !objB.hasOwnProperty(key) ||
</div><div class="hljs-line">      !<span class="hljs-built_in">Object</span>.is(objA[key], objB[key])
</div><div class="hljs-line">    ) {
</div><div class="hljs-line">      <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
</div><div class="hljs-line">    }
</div><div class="hljs-line">  }
</div><div class="hljs-line">  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
</div><div class="hljs-line">};
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-comment">// 测试使用</span>
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Demo</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{
</div><div class="hljs-line">    ...
</div><div class="hljs-line">    shouldComponentUpdate(nextProps, nextState) {
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> !shallowEqual(<span class="hljs-keyword">this</span>.props, nextProps) ||
</div><div class="hljs-line">            !shallowEqual(<span class="hljs-keyword">this</span>.state, nextState);
</div><div class="hljs-line">    }
</div><div class="hljs-line">    ...
</div><div class="hljs-line">};
</div></code></pre>

    <h4 id="非受控组件">非受控组件</h4>
    <p>不受状态管控的组件「可以基于ref获取DOM元素进行操作」</p>
    <ul>
      <li>
        <p>ref=’xxx’ <code>不推荐使用</code></p>
      </li>
      <li>
        <p>ref={x=&gt;this.xxx=x}</p>
      </li>
      <li>
        <p>React.createRef</p>
      </li>
    </ul>
    <p>赋值给标签，目的是获取DOM元素； <br>
      赋值给类组件，目的是获取组件的实例； <br>
      函数组件不能直接设置ref，但是可以基于<code>React.forwardRef  /ˈfɔːwəd/</code>实现ref转发！</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-comment">// 被调用的子组件</span>
</div><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">const</span> Demo3 = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Demo3</span>(<span class="hljs-params">props, ref</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"demo3"</span></span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-attr">ref</span>=<span class="hljs-string">{ref}</span>&gt;</span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> React.forwardRef(Demo3);
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-comment">// 父组件</span>
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Demo</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{
</div><div class="hljs-line">    componentDidMount() {
</div><div class="hljs-line">        <span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">this</span>.box); <span class="hljs-comment">//-&gt; div.demo3</span>
</div><div class="hljs-line">    }
</div><div class="hljs-line">    render() {
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"demo"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">Demo3</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{x</span> =&gt;</span> this.box = x} /&gt;</span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>;</span>
</div><div class="hljs-line"><span class="xml">    }</span>
</div><div class="hljs-line"><span class="xml">};</span>
</div></code></pre>

    <h4 id="关于setstate的进阶研究">关于setState的进阶研究</h4>
    <p>React18中，对于setState的操作，采用了 <code>批处理</code>！</p>
    <ul>
      <li>
        <p>构建了队列机制</p>
      </li>
      <li>
        <p>统一更新，提高视图更新的性能</p>
      </li>
      <li>
        <p>处理流程更加稳健</p>
      </li>
    </ul>

    <p>在React 18之前，我们只在 <code>React合成事件/周期函数</code>期间批量更新；默认情况下，React中不会对 promise、setTimeout、原生事件处理（native event
      handlers）或其它React默认不进行批处理的事件进行批处理操作！</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Demo</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{
</div><div class="hljs-line">    state = {
</div><div class="hljs-line">        <span class="hljs-attr">x</span>: <span class="hljs-number">10</span>,
</div><div class="hljs-line">        <span class="hljs-attr">y</span>: <span class="hljs-number">5</span>,
</div><div class="hljs-line">        <span class="hljs-attr">z</span>: <span class="hljs-number">0</span>
</div><div class="hljs-line">    };
</div><div class="hljs-line">    handler = <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
</div><div class="hljs-line">        <span class="hljs-keyword">let</span> { x, y, z } = <span class="hljs-keyword">this</span>.state;
</div><div class="hljs-line">        <span class="hljs-keyword">this</span>.setState({ <span class="hljs-attr">x</span>: x + <span class="hljs-number">1</span> });
</div><div class="hljs-line">        <span class="hljs-keyword">this</span>.setState({ <span class="hljs-attr">y</span>: y + <span class="hljs-number">1</span> });
</div><div class="hljs-line">        <span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">this</span>.state);
</div><div class="hljs-line">        setTimeout(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
</div><div class="hljs-line">            <span class="hljs-keyword">this</span>.setState({ <span class="hljs-attr">z</span>: z + <span class="hljs-number">1</span> });
</div><div class="hljs-line">            <span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">this</span>.state);
</div><div class="hljs-line">        });
</div><div class="hljs-line">    };
</div><div class="hljs-line">    render() {
</div><div class="hljs-line">        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'render'</span>);
</div><div class="hljs-line">        <span class="hljs-keyword">let</span> { x, y, z } = <span class="hljs-keyword">this</span>.state;
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"demo"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            {x}-{y}-{z}</span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{this.handler}</span>&gt;</span>处理<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
</div><div class="hljs-line">    }
</div><div class="hljs-line">};
</div></code></pre>

    <p>setState接收的参数还可以是一个函数，在这个函数中可以拿先前的状态，并通过这个函数的返回值得到下一个状态</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Demo</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{
</div><div class="hljs-line">    state = {
</div><div class="hljs-line">        <span class="hljs-attr">num</span>: <span class="hljs-number">0</span>
</div><div class="hljs-line">    };
</div><div class="hljs-line">    componentDidMount() {
</div><div class="hljs-line">        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">100</span>; i++) {
</div><div class="hljs-line">            <span class="hljs-comment">/* this.setState({ num: this.state.num + 1 });</span>
</div><div class="hljs-line"><span class="hljs-comment">            console.log(this.state.num); */</span>
</div><div class="hljs-line">            <span class="hljs-keyword">this</span>.setState(<span class="hljs-function"><span class="hljs-params">prevState</span> =&gt;</span> {
</div><div class="hljs-line">                <span class="hljs-keyword">return</span> {
</div><div class="hljs-line">                    <span class="hljs-attr">num</span>: prevState.num + <span class="hljs-number">1</span>
</div><div class="hljs-line">                };
</div><div class="hljs-line">            });
</div><div class="hljs-line">        }
</div><div class="hljs-line">    }
</div><div class="hljs-line">    render() {
</div><div class="hljs-line">        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'render'</span>);
</div><div class="hljs-line">        <span class="hljs-keyword">let</span> { num } = <span class="hljs-keyword">this</span>.state;
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"demo"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            {num}</span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
</div><div class="hljs-line">    }
</div><div class="hljs-line">};
</div></code></pre>

    <p>基于<code>flushSync</code>可以清空队列</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { flushSync } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Demo</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{
</div><div class="hljs-line">    state = {
</div><div class="hljs-line">        <span class="hljs-attr">x</span>: <span class="hljs-number">10</span>,
</div><div class="hljs-line">        <span class="hljs-attr">y</span>: <span class="hljs-number">5</span>,
</div><div class="hljs-line">        <span class="hljs-attr">z</span>: <span class="hljs-number">0</span>
</div><div class="hljs-line">    };
</div><div class="hljs-line">    handler = <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
</div><div class="hljs-line">        <span class="hljs-keyword">let</span> { x, y, z } = <span class="hljs-keyword">this</span>.state;
</div><div class="hljs-line">        <span class="hljs-keyword">this</span>.setState({ <span class="hljs-attr">x</span>: x + <span class="hljs-number">1</span> });
</div><div class="hljs-line">        flushSync(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
</div><div class="hljs-line">            <span class="hljs-keyword">this</span>.setState({ <span class="hljs-attr">y</span>: y + <span class="hljs-number">1</span> });
</div><div class="hljs-line">        });
</div><div class="hljs-line">        <span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">this</span>.state); <span class="hljs-comment">// x:11 y:6 z:0 -&gt; render</span>
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">        <span class="hljs-keyword">this</span>.setState({ <span class="hljs-attr">z</span>: z + <span class="hljs-number">1</span> });
</div><div class="hljs-line">        <span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">this</span>.state);
</div><div class="hljs-line">    };
</div><div class="hljs-line">    render() {
</div><div class="hljs-line">        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'render'</span>);
</div><div class="hljs-line">        <span class="hljs-keyword">let</span> { x, y, z } = <span class="hljs-keyword">this</span>.state;
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"demo"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            {x}-{y}-{z}</span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{this.handler}</span>&gt;</span>处理<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
</div><div class="hljs-line">    }
</div><div class="hljs-line">};
</div></code></pre>
  </div>
</body>

</html>